package com.bf.electroplating.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bf.electroplating.login.UserContext;
import com.bf.electroplating.login.UserDetail;
import com.bf.electroplating.mapper.SysUserMapper;
import com.bf.electroplating.pojo.dto.IdDTO;
import com.bf.electroplating.pojo.dto.sysuser.AdminUserDetailDTO;
import com.bf.electroplating.pojo.dto.sysuser.AdminUserPageDTO;
import com.bf.electroplating.pojo.entity.*;
import com.bf.electroplating.pojo.enums.AttModuleEnums;
import com.bf.electroplating.pojo.vo.ResultVO;
import com.bf.electroplating.pojo.vo.SelectVo;
import com.bf.electroplating.pojo.vo.sysuser.AdminUserVO;
import com.bf.electroplating.pojo.vo.sysuser.UserListVO;
import com.bf.electroplating.service.*;
import com.bf.electroplating.util.DESUtil;
import com.bf.electroplating.util.MD5Util;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * (用户表)SYS_USER 服务实现类
 * </p>
 *
 * @author xxx
 * @since 2024-10-18
 */
@Service
public class SysUserServiceImpl extends ServiceImpl < SysUserMapper,SysUser > implements ISysUserService {

    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private ISysUserRoleService sysUserRoleService;
    @Resource
    private ISysRoleService sysRoleService;
    @Resource
    private ISysRoleFunctionService sysRoleFunctionService;
    @Resource
    private ComCompanyService companyService;
    @Resource
    private PubParamDictionaryService pubParamService;
    @Resource
    private PubAttachmentService pubAttachmentService;
    @Resource
    private PubAttachmentRelService pubAttachmentRelService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    private final String SALT="biekanwozhishiyizhiyang";

    @Override
    public ResultVO <Page< AdminUserVO >> getAdminList( AdminUserPageDTO dto) {
        Page<SysUser> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(dto.getRoleId())){
            List< SysUserRole > sysUserRoles = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRId, dto.getRoleId()));
            if (!sysUserRoles.isEmpty()){
                wrapper.in(SysUser::getId, sysUserRoles.stream().map(SysUserRole::getUId).collect(Collectors.toList()));
            }else {
                return ResultVO.ok(null);
            }
        }
        List<ComCompany> company = companyService.list();
        Map<String, String> companyMap = company.stream().collect(Collectors.toMap(ComCompany::getId, ComCompany::getCompanyName));
        List<SelectVo> park = pubParamService.getParamList("PARK").getData();
        Map<String, String> parkMap = park.stream().collect(Collectors.toMap(SelectVo::getId, SelectVo::getName));
        Page<SysUser> userPage = page(page, wrapper
                .eq(StringUtils.isNotBlank(dto.getCompanyId()), SysUser::getCompanyId, dto.getCompanyId())
                .eq(StringUtils.isNotBlank(dto.getParkId()), SysUser::getParkId, dto.getParkId())
                .like(StringUtils.isNotBlank(dto.getUserAccountName()), SysUser::getUserAccountName, dto.getUserAccountName())
                .like(StringUtils.isNotBlank(dto.getUserName()), SysUser::getUserName, dto.getUserName()));
        Page<AdminUserVO> sysUserPage = new Page<>();
        BeanUtils.copyProperties(userPage, sysUserPage);
        List<AdminUserVO> adminUserVOS = new ArrayList<>();
        userPage.getRecords().forEach(i -> {
            AdminUserVO adminUserVO = new AdminUserVO();
            BeanUtils.copyProperties(i, adminUserVO);
            adminUserVO.setCompanyName(companyMap.get(adminUserVO.getCompanyId()));
            adminUserVO.setParkName(parkMap.get(adminUserVO.getParkId()));
            List<SysUserRole> sysUserRoles = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>()
                    .eq(SysUserRole::getUId, i.getId()));
            if (!sysUserRoles.isEmpty()){
                adminUserVO.setRoleName(sysRoleService.listByIds(sysUserRoles.stream().map(SysUserRole::getRId).collect(Collectors.toList())).stream().map( SysRole::getRoleName).collect(Collectors.joining("、")));
            }
            adminUserVOS.add(adminUserVO);
        });
        sysUserPage.setRecords(adminUserVOS);
        return ResultVO.ok(sysUserPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVO<Object> saveOrUpdateAdmin(AdminUserDetailDTO dto, HttpServletRequest request) {
        SysUser sysUserOne = getOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUserAccountName, dto.getUserAccountName()));
        Set<String> functionIds = new HashSet<>();
        for (String roleId : dto.getRoleIds ()) {
            functionIds.addAll(sysRoleFunctionService.list(new LambdaQueryWrapper< SysRoleFunction >().eq(SysRoleFunction::getRId, roleId)).stream().map(SysRoleFunction::getFId).collect(Collectors.toList()));
        }


        if (dto.getId() == null && sysUserOne != null) {
            return ResultVO.fail(null, "账号已存在，请重新输入！");
        }
        if (!dto.getPassword().equals(dto.getPasswordAgain())) {
            return ResultVO.fail(null, "两次输入的密码不一致，请重新输入！");
        }
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(dto, sysUser);
        try {
            sysUser.setPassword( MD5Util.MD5Encode(MD5Util.MD5Encode( DESUtil.decryptByDES(dto.getPassword())+SALT)));
        } catch (Exception e) {
            log.error("密码加密失败", e);
            throw new RuntimeException(e);
        }
        saveOrUpdate(sysUser);

        if (dto.getId() != null) {
            sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>()
                    .eq(SysUserRole::getUId, sysUser.getId()));
        }

        dto.getRoleIds().forEach(i -> {
            SysUserRole selectedRole = new SysUserRole();
            selectedRole.setRId(i);
            selectedRole.setUId(sysUser.getId());
            sysUserRoleService.save(selectedRole);
        });

        pubAttachmentRelService.remove(new LambdaQueryWrapper<PubAttachmentRel>()
                .eq(PubAttachmentRel::getStorePath, AttModuleEnums.USER_PHOTO.getCode())
                .eq(PubAttachmentRel::getRelationId, sysUser.getId()));
        if (dto.getAttachmentVo() != null && dto.getAttachmentVo().getId() != null) {
            pubAttachmentService.saveOnePubAttachmentRel(dto.getAttachmentVo(), sysUser.getId(), AttModuleEnums.USER_PHOTO.getCode());
        }
        UserDetail user = UserContext.getUser();
        if (dto.getId()!= null && dto.getId().equals( user.getId())){
            user.setUserName(sysUser.getUserName());
            user.setAttachmentVo(dto.getAttachmentVo());
            String token = request.getHeader("token");
            saveUser(token, user);
        }
        ComCompany company=companyService.getById(dto.getCompanyId());
        if (company!=null){
            user.setBelongSewageCode(company.getBelongSewageCode());
        }
        return ResultVO.ok(null, "操作成功");
    }

    private final static String TOKEN_PREFIX = "user:";

    // 保存用户信息到 Redis
    public void saveUser(String token, UserDetail userInfo) {
        redisTemplate.opsForValue().set(TOKEN_PREFIX + token, JSON.toJSONString(userInfo), 1, TimeUnit.DAYS);  // 设置过期时间为1天
    }

    @Override
    public ResultVO<Object> deleteAdmin( IdDTO dto) {
        UserDetail user = UserContext.getUser();
        if ( user.getId ().equals ( dto.getId () ) ) {
            return ResultVO.fail(null, "用户不能删除自己账号");
        }
        sysUserMapper.deleteById(dto.getId());
        sysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUId, dto.getId()));
        return ResultVO.ok(null, "删除成功");
    }

    @Override
    public ResultVO<AdminUserDetailDTO> getDetailAdmin(IdDTO dto) {
        SysUser sysUser = getById(dto.getId());
        AdminUserDetailDTO adminUserDetailDTO = new AdminUserDetailDTO();
        BeanUtils.copyProperties(sysUser, adminUserDetailDTO);
        adminUserDetailDTO.setPassword(null);
        List<SysUserRole> sysUserRoles = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>()
                .eq(SysUserRole::getUId, sysUser.getId()));
        adminUserDetailDTO.setRoleIds(sysUserRoles.stream().map(SysUserRole::getRId).collect(Collectors.toList()));
        adminUserDetailDTO.setAttachmentVo(pubAttachmentService.getOneFile(sysUser.getId(), AttModuleEnums.USER_PHOTO.getCode()));
        return ResultVO.ok(adminUserDetailDTO);
    }

    @Override
    public ResultVO<List<UserListVO>> getUserListVO() {
        List<SysUser> list = list();
        if (!list.isEmpty()){
            // 封装VO
            List<UserListVO> userListVOS = list.stream().map(i -> {
                UserListVO vo = new UserListVO();
                BeanUtils.copyProperties(i, vo);
                return vo;
            }).toList();
            return ResultVO.ok(userListVOS);
        }
        return ResultVO.ok(null);
    }

    @Override
    public List<UserListVO> getUserListVOByRoleCode(String roleCode) {
        SysRole sysRole = sysRoleService.getOne(new LambdaQueryWrapper<SysRole>().eq(SysRole::getRoleCode, roleCode));
        List<SysUserRole> sysUserRoles = sysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRId, sysRole.getId()));
        if (!sysUserRoles.isEmpty()){
            List<SysUser> users = listByIds(sysUserRoles.stream().map(SysUserRole::getUId).collect(Collectors.toList()));
            if (!users.isEmpty()){
                return users.stream().map(i -> {
                    UserListVO vo = new UserListVO();
                    BeanUtils.copyProperties(i, vo);
                    return vo;
                }).toList();
            }
        }
        return null;
    }
}
